package docker_server

import (
	"context"
	"errors"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/network"
	"github.com/docker/docker/client"
	"time"
)

type DockerServer struct {
	//docker客户端
	client *client.Client
	//docker容器列表
	DockerContainers []DockerContainer
	//docker镜像列表
	DockerImages []types.ImageSummary
}

// NewDockerServer 创建一个新的DockerServer实例
func NewDockerServer() (*DockerServer, error) {
	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
	if err != nil {
		return nil, err
	}
	return &DockerServer{client: cli}, nil
}

// ListContainers 列出所有容器
func (ds *DockerServer) ListContainers() ([]types.Container, error) {
	containers, err := ds.client.ContainerList(context.Background(), types.ContainerListOptions{
		All: true,
	})
	if err != nil {
		return nil, err
	}
	return containers, nil
}

// ListImages 列出所有镜像
func (ds *DockerServer) ListImages() ([]types.ImageSummary, error) {
	images, err := ds.client.ImageList(context.Background(), types.ImageListOptions{})
	if err != nil {
		return nil, err
	}
	return images, nil
}

// CheckContainerStatus 检查容器状态
func (ds *DockerServer) CheckContainerStatus(containerID string) (string, error) {
	containerJSON, err := ds.client.ContainerInspect(context.Background(), containerID)
	if err != nil {
		return "", err
	}
	return containerJSON.State.Status, nil
}

// RestartContainer 重启容器
func (ds *DockerServer) RestartContainer(containerID string) error {
	err := ds.client.ContainerRestart(context.Background(), containerID, container.StopOptions{})

	if err != nil {
		return err
	}

	//暂停两秒
	time.Sleep(2 * time.Second)

	//验证目前容器状态
	containStatus, err := ds.CheckContainerStatus(containerID)

	if err != nil {
		return err
	}

	if containStatus == "exited" {
		return errors.New(("容器未正常重启"))
	}
	return nil
}

func (ds *DockerServer) StopContainer(containerID string) error {
	err := ds.client.ContainerStop(context.Background(), containerID, container.StopOptions{Timeout: nil})

	if err != nil {
		return err
	}

	// 可以选择等待一段时间后检查容器状态
	time.Sleep(2 * time.Second)

	// 验证容器状态
	containStatus, err := ds.CheckContainerStatus(containerID)
	if err != nil {
		return err
	}

	if containStatus != "exited" {
		return errors.New("容器未正常停止")
	}

	return nil
}

// StartContainer 启动容器
func (ds *DockerServer) StartContainer(containerID string) error {
	return ds.client.ContainerStart(context.Background(), containerID, types.ContainerStartOptions{})
}

// CreateContainer 新建容器
func (ds *DockerServer) CreateContainer(containerConfig *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (container.CreateResponse, error) {
	return ds.client.ContainerCreate(context.Background(), containerConfig, hostConfig, networkingConfig, nil, containerName)
}

// GetContainerCommand 获取容器创建命令
func (ds *DockerServer) GetContainerCommand(containerID string) ([]string, error) {
	containerJSON, err := ds.client.ContainerInspect(context.Background(), containerID)
	if err != nil {
		return nil, err
	}
	return containerJSON.Config.Cmd, nil
}

// ExecCommandInContainer 在容器内执行命令
func (ds *DockerServer) ExecCommandInContainer(containerID string, cmd []string) error {
	ctx := context.Background()
	execConfig := types.ExecConfig{
		Cmd:          cmd,
		AttachStdout: true,
		AttachStderr: true,
	}
	execID, err := ds.client.ContainerExecCreate(ctx, containerID, execConfig)
	if err != nil {
		return err
	}

	return ds.client.ContainerExecStart(ctx, execID.ID, types.ExecStartCheck{})
}
